#!/usr/bin/env python
#
# Copyright 2007 Cameron Tangney (cameront at gmail dot com)
#

import datetime
import os
import wsgiref.handlers

import gdata.photos.service
import gdata.media
import gdata.geo
import gdata.alt.appengine
import gdata.service
import gdata.urlfetch

from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template


# ================
#     MODELS
# ================

class UserAlbums(db.Model):
  # Key = email-album_id
  album_id = db.StringProperty()
  comments_feed_uri = db.LinkProperty()
  email = db.EmailProperty()
  feed_uri = db.LinkProperty()
  is_private = db.BooleanProperty()
  is_published = db.BooleanProperty()
  numcomments = db.IntegerProperty()
  numphotos = db.IntegerProperty()
  title = db.StringProperty()
  updated = db.DateTimeProperty()
  username = db.StringProperty()


# ================
#     HANDLERS
# ================

class BaseHandler(webapp.RequestHandler):
  
  def __init__(self):
    self.user = users.get_current_user()
    self.username = None
    if self.user:
      self.username = self.user.nickname()
    self.client = gdata.photos.service.PhotosService()
    gdata.alt.appengine.run_on_appengine(self.client, True)

  def get_album_by_id(self, album_id, username=None):
    if not username and self.user:
      username = self.user.nickname()
    query = UserAlbums.gql("WHERE username = :u AND album_id = :album_id", 
      u=username, album_id=album_id)
    return query.get()

  def get_albums_by_user(self, username=None):
    if not username and self.user:
      username = self.user.nickname()
    query = UserAlbums.gql("WHERE username = :u", u=username)
    return query.fetch(1000)

  def get_datetime_from_datestring(self, datestring):
    update_a = datestring.partition('T')
    date_a = update_a[0].split('-')
    time_a = update_a[2].split(':')
    return datetime.datetime(int(date_a[0]), int(date_a[1]), 
      int(date_a[2]), int(time_a[0]), int(time_a[1]), int(time_a[2].split(".")[0]))

  def get_grant_access_url(self, next):
    """Gets the URL that grants this app access to private picasa data"""
    scope = 'http://picasaweb.google.com/data/'
    secure = False
    session = True
    return self.client.GenerateAuthSubURL('/user/grant', scope, secure, session);

  def login_or_redirect(self, next):
    if not self.user:
      self.redirect(users.create_login_url(next))
  
  def render_template(self, template_name, template_values):
    email = None
    username = None
    if self.user:
      email = self.user.email()
      username = self.user.email().split('@')[0]

    values = {
      'email' : email,
      'username' : username,
      'logout_url' : users.create_logout_url('/'),
      'login_url' : users.create_login_url(self.request.uri),
    }
    for key,value in template_values.items():
      values[key] = value

    path = os.path.join(os.path.dirname(__file__), 'templates/%s' %template_name)
    self.response.out.write(template.render(path, values))
    

class MainHandler(BaseHandler):
  def get(self): 
    template_values = {
      'page_title' : 'Welcome to Photo Organizer',
    }
    self.render_template('index.html', template_values)


class FeedViewHandler(BaseHandler):
  def getCommentFromEntry(self, entry):
    updatetime = self.get_datetime_from_datestring(entry.updated.text)
    return {'date':updatetime, 'comment':entry}

  def getCommentsByPhotoId(self, album):
    comments = self.client.GetFeed(album.comments_feed_uri)
    comment_dict = {}
    for comment in comments.entry:
      key = comment.photoid.text
      if comment_dict.has_key(key):
        comment_dict[key].append(self.getCommentFromEntry(comment))
      else:
        comment_dict[key] = [self.getCommentFromEntry(comment)]
    return comment_dict

  def get(self):
    album_id = str(self.request.get('a'))
    username = str(self.request.get('u'))
    album = self.get_album_by_id(album_id,username)
    
    photos = self.client.GetFeed(album.feed_uri)
      
    comment_dict = None
    for photo in photos.entry:      
      if photo.commentCount > 0:
        comment_dict = self.getCommentsByPhotoId(album)
        break
        
    template_values = {
      'page_title' : photos.title.text,
      'album_description' : photos.subtitle.text,
      'entries': photos.entry,
      'comment_dict' : comment_dict,
    }
    self.render_template('view_feed.html', template_values)
        

class MyFeedListHandler(BaseHandler):
  def get(self):
    albums = self.client.GetUserFeed(user=self.user.nickname())

    published_feeds_dict = {}
    for k in self.get_albums_by_user():
      published_feeds_dict[k.album_id] = k

    feeds = []
    granted = False
    for album in albums.entry:
      album.is_published = published_feeds_dict.has_key(album.gphoto_id.text)
      album.formatted_update = album.updated.text.split('T')[0]
      album.is_public = (album.rights.text.lower() == 'public')
      if not album.is_public:
        granted = True
      feeds.append(album)
        
    template_values = {
      'page_title' : "%s's feeds" %self.user.nickname(),
      'feeds': feeds,
      'granted': granted,
      'grant_url' : self.get_grant_access_url(self.request.uri),
    }
    self.render_template('user_feeds.html', template_values)


class GrantHandler(BaseHandler):
  def get(self):
    """Stores the token and redirects to wherever the user wanted to go."""
    auth_token = gdata.auth.extract_auth_sub_token_from_url(self.request.uri)
    session_token = None
    if auth_token:
      # Upgrade the single-use AuthSub token to a multi-use session token.
      session_token = self.client.UpgradeToSessionToken(auth_token)
    if session_token and users.get_current_user():
      # If there is a current user, store the token in the datastore and
      # associate it with the current user. Since we told the client to
      # run_on_appengine, the add_token call will automatically store the
      # session token if there is a current_user.
      self.client.token_store.add_token(session_token)
      self.redirect('/my/feeds')


class PublishHandler(BaseHandler):
  def get(self):
    album_id = str(self.request.get('a'))
    feed_uri = '/data/feed/api/user/%s/albumid/%s?kind=%s' %(
      self.user.nickname(), album_id, 'photo')
    feed = self.client.GetFeed(feed_uri)
    print feed.commentCount.text
    album = UserAlbums.get_or_insert(
      '%s-%s'%(self.user.nickname(), album_id),
      album_id=album_id, 
      comments_feed_uri=feed.GetCommentsUri(),
      email=self.user.email(), 
      feed_uri=feed.GetPhotosUri(),
      is_private=feed.rights.text.lower()=='private', 
      is_published=True, 
      numcomments=int(feed.commentCount.text), 
      numphotos=int(feed.numphotos.text), 
      title=feed.title.text, 
      updated=self.get_datetime_from_datestring(feed.updated.text),
      username=self.user.nickname())
    album.put()
    self.redirect('/my/feeds')
  

class UnPublishHandler(BaseHandler):
  def get(self):
    album_id = str(self.request.get('a'))
    album = self.get_album_by_id(album_id)
    if album:
      album.delete()
    self.redirect('/my/feeds')


class UserFeedsHandler(BaseHandler):
  def get(self):
    username = str(self.request.get('u'))
    if username:
      albums = self.get_albums_by_user(username)
    else:
      albums = UserAlbums.all()

    albums_by_username = {}
    for album in albums:
      if albums_by_username.has_key(album.username):
        albums_by_username[album.username].append(album)
      else:
        albums_by_username[album.username] = [album]

    useralbums = []
    for key in albums_by_username:
      value = albums_by_username[key]
      useralbums.append({'username':value[0].username, 'albums':value})

    template_values = {
      'page_title' : "%s's albums" %username,
      'alluseralbums' : useralbums,
      'current_username' : self.username,
    }
    self.render_template('all_feeds.html', template_values)


def main():
  application = webapp.WSGIApplication([('/', MainHandler),
                                        ('/feed', FeedViewHandler),
                                        ('/my/feeds', MyFeedListHandler),
                                        ('/my/grant', GrantHandler),
                                        ('/my/publish', PublishHandler),
                                        ('/my/unpublish', UnPublishHandler),
                                        ('/user', UserFeedsHandler),
                                        ],
                                       debug=True)
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()









  #class AuthenticatedHandler(BaseHandler):
  #  def get(self):
  #    if self.user:
  #      self.authenticated_get()
  #    else:
  #      # If overridden, subclasses can answer unauthenticated requests.
  #      self.unauthenticated_get()
  #    
  #  def unauthenticated_get(self):
  #    """The default behavior for unauthenticated requests is a redirect to the 
  #       login page."""
  #    print 'hello'
  #    self.login_or_redirect('/')
